package dao

import (
	"fmt"
	"time"
	models "yuanaiproblem/dao/model" // 导入试卷相关模型
	"yuanaiproblem/migrations/db"    // 导入数据库连接
	"yuanaiproblem/models/dto"       // 导入数据传输对象

	"gorm.io/gorm" // 导入gorm ORM库
)

// CreatePaper 创建试卷（事务）
// 入参事务对象和试卷指针，返回操作结果
func CreatePaper(tx *gorm.DB, paper *models.Paper) error {
	return tx.Create(paper).Error
}

// CreatePaperQuestions 创建试卷题目关联（事务）
// 批量创建试卷与题目的关联关系
func CreatePaperQuestions(tx *gorm.DB, pqs []models.PaperQuestion) error {
	return tx.Create(&pqs).Error
}

// GetPapersByUserID 查询用户创建的试卷
// 查未删除的试卷，按创建时间倒序
func GetPapersByUserID(userID int32) ([]models.Paper, error) {
	var papers []models.Paper // 存储查询到的试卷
	// 条件查询：创建者ID匹配且未删除
	result := db.DB.Where("creator_id = ?", userID).
		Where("deleted_at IS NULL").
		Order("created_at DESC").
		Find(&papers)
	return papers, result.Error
}

// GetPaperByID 查询试卷
// 按ID查询试卷详情
func GetPaperByID(id uint) (*models.Paper, error) {
	var paper models.Paper // 存储查询到的试卷
	result := db.DB.First(&paper, id)
	return &paper, result.Error
}

// UpdateQuestionOrder 更新题目顺序（事务）
// 批量更新试卷中题目的排序
func UpdateQuestionOrder(tx *gorm.DB, paperID uint, items []dto.QuestionOrderItem) error {
	// 遍历更新每个题目的顺序
	for _, item := range items {
		if err := tx.Model(&models.PaperQuestion{}).
			Where("paper_id = ? AND question_id = ?", paperID, item.QuestionID).
			Update("question_order", item.QuestionOrder).Error; err != nil {
			return err
		}
	}
	return nil
}

// CountPaperQuestions 统计试卷题目数量（事务）
// 统计指定试卷中包含的有效题目数
func CountPaperQuestions(tx *gorm.DB, paperID uint, questionIDs []uint) (int64, error) {
	var count int64 // 存储统计结果
	return count, tx.Model(&models.PaperQuestion{}).
		Where("paper_id = ? AND question_id IN ?", paperID, questionIDs).
		Count(&count).Error
}

// GetUserPapers 分页查询用户试卷(仅返回未删除的)
// 按用户ID分页查询试卷，返回列表、总数和错误
func GetUserPapers(userID int32, page, pageSize int) ([]models.Paper, int64, error) {
	// 构建查询条件
	query := db.DB.Model(&models.Paper{}).Where("creator_id = ?", userID).Where("deleted_at IS NULL")

	var total int64 // 总记录数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 计算分页偏移量
	offset := (page - 1) * pageSize
	var papers []models.Paper // 存储查询到的试卷
	// 执行分页查询，按创建时间倒序
	if err := query.
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&papers).Error; err != nil {
		return nil, 0, err
	}

	return papers, total, nil
}

// GetUserPapers 分页查询用户试卷(包含已删除+未删除的)
// 按用户ID分页查询试卷，返回列表、总数和错误
func GetUserAllPapers(userID int32, page, pageSize int) ([]models.Paper, int64, error) {
	// 构建查询条件
	query := db.DB.Model(&models.Paper{}).Where("creator_id = ?", userID)

	var total int64 // 总记录数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 计算分页偏移量
	offset := (page - 1) * pageSize
	var papers []models.Paper // 存储查询到的试卷
	// 执行分页查询，按创建时间倒序
	if err := query.
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&papers).Error; err != nil {
		return nil, 0, err
	}

	return papers, total, nil
}

// GetPaperQuestion 查找试卷题目关联
// 查询试卷与特定题目的关联关系
func GetPaperQuestion(tx *gorm.DB, paperID, questionID uint) (*models.PaperQuestion, error) {
	var pq models.PaperQuestion // 存储关联关系
	result := tx.Where("paper_id = ? AND question_id = ?", paperID, questionID).First(&pq)
	return &pq, result.Error
}

// DeletePaperQuestion 软删除试卷题目关联
// 从试卷中移除特定题目（软删除）
func DeletePaperQuestion(tx *gorm.DB, pq *models.PaperQuestion) error {
	return tx.Delete(pq).Error
}

// UpdateQuestionOrdersAfterDelete 更新删除后的题目顺序
// 删除题目后，调整剩余题目的排序
func UpdateQuestionOrdersAfterDelete(tx *gorm.DB, paperID uint, deletedOrder int32) error {
	// 对序号大于被删除题目的记录，序号减1
	return tx.Model(&models.PaperQuestion{}).
		Where("paper_id = ? AND question_order > ?", paperID, deletedOrder).
		Update("question_order", gorm.Expr("question_order - 1")).Error
}

// UpdatePaperDeletedAt 更新试卷删除时间
// 用于软删除试卷
func UpdatePaperDeletedAt(paper *models.Paper, deletedAt time.Time) error {
	return db.DB.Model(paper).Update("deleted_at", deletedAt).Error
}

// GetPaperQuestionsWithDetails 查询试卷题目详情
// 查询试卷包含的所有题目及详情，按顺序排列
func GetPaperQuestionsWithDetails(paperID uint) ([]models.PaperQuestion, error) {
	var pqs []models.PaperQuestion // 存储试卷题目关联列表
	// 预加载题目详情，按顺序查询
	err := db.DB.
		Preload("Question").
		Where("paper_id = ?", paperID).
		Order("question_order ASC").
		Find(&pqs).Error
	return pqs, err
}

// GetQuestionByIDForPaper 查询题目
// 用于获取试卷关联的题目详情
func GetQuestionByIDForPaper(id uint) (*models.Question, error) {
	var question models.Question // 存储查询到的题目
	result := db.DB.First(&question, id)
	return &question, result.Error
}

// CreatePaperQuestion 添加题目到试卷
// 创建试卷与题目的关联关系
func CreatePaperQuestion(pq *models.PaperQuestion) error {
	return db.DB.Create(pq).Error
}

// CheckQuestionInPaper 检查题目是否已在试卷中
// 判断题目是否已添加到指定试卷
func CheckQuestionInPaper(paperID, questionID uint) (bool, error) {
	var count int64 // 存储匹配数量
	err := db.DB.Model(&models.PaperQuestion{}).
		Where("paper_id = ? AND question_id = ?", paperID, questionID).
		Count(&count).Error
	return count > 0, err
}

// GetAllPapers 分页查询所有试卷
// 分页查询系统中所有试卷
// GetAllPapers 分页查询所有试卷
// 入参：页码、每页条数
// 返回：试卷列表、总记录数和错误
func GetAllPapers(page, pageSize int) ([]models.Paper, int64, error) {
	// 分页参数校验与默认值处理
	if page < 1 {
		page = 1 // 页码默认值为1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 10 // 页大小默认10，最大限制100条
	}

	// 计算偏移量（参数已校验，避免负数）
	offset := (page - 1) * pageSize

	// 查询总记录数（排除软删除数据）
	var total int64
	query := db.DB.Model(&models.Paper{}).Where("deleted_at IS NULL") // 只查未删除的试卷
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询试卷（按ID倒序，排除软删除）
	var papers []models.Paper
	if err := query.
		Order("id DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&papers).Error; err != nil {
		return nil, 0, err
	}

	// 调试信息
	fmt.Printf("试卷查询参数：page=%d, pageSize=%d, offset=%d, 总记录数=%d\n",
		page, pageSize, offset, total)

	return papers, total, nil
}

// FindValidQuestionIDs 查找有效的题目ID
// 从给定ID列表中筛选出存在的题目ID
func FindValidQuestionIDs(questionIDs []int32) ([]int32, error) {
	var existingIDs []int32 // 存储有效的题目ID
	err := db.DB.Model(&models.Question{}).
		Where("id IN (?)", questionIDs).
		Pluck("id", &existingIDs).Error
	return existingIDs, err
}
